package folder.model.link;

import java.util.ArrayList;
import java.util.List;

import folder.model.network.Network;
import folder.model.node.Node;
import folder.model.virtual.VirtualLink;

public class Link
{	
	// Link
	
	public static Link link( int identifier, double bandwidth, double distanceInKm, Node nodeA, Node nodeB, Network network )
	{
		return new Link( identifier, bandwidth, distanceInKm, nodeA, nodeB, network );
	}
	public Link( int identifier, double bandwidth, double distanceInKm, Node nodeA, Node nodeB, Network network )
	{
		this.identifier = identifier;
		this.bandwidthTotal = bandwidth;
		this.distanceInKm = distanceInKm;
		this.nodeA = nodeA;
		this.nodeB = nodeB;
		this.network = network;
		
		this.bandwidthAvailable = bandwidth;
		
		this.connect();
	}
	
	private final int identifier;
	public int getIdentifier(){ return this.identifier; }
	
	private final double bandwidthTotal;
	public double getBandwidthTotal(){ return this.bandwidthTotal; }
	
	private final double distanceInKm;
	public double getDistanceInKm(){ return this.distanceInKm; }
	
	private final Node nodeA;
	public Node getNodeA(){ return this.nodeA; }
	
	private final Node nodeB;
	public Node getNodeB(){ return this.nodeB; }
	
	public String toString(){ return "(" + nodeA.getIdentifier() + "_" + nodeB.getIdentifier() + ") " + this.getVirtualLinks().toString(); }
	
	private final Network network;
	public final Network getNetwork(){ return this.network; }
	
	// Path
	
	private double delay = 0;
	public double getDelay(){ return this.delay; }
	public void disconnect(){ delay = Double.POSITIVE_INFINITY; }
	public void connect(){ delay = distanceInKm / 300000; }
	
	private double numberPaths = 0;
	public double getNumberPaths(){ return this.numberPaths; }
	public void incrementNumberPaths(){ numberPaths++; }
	public void resetNumberPaths(){ numberPaths = 0; }
	
	// Allocation
	
	private double bandwidthAvailable;
	public double getBandwidthAvailable(){ return this.bandwidthAvailable; }
	public void allocateBandwidthAvailable( double bandwidth ){ bandwidthAvailable -= bandwidth; }
	public void resetBandwidthAvailable(){ bandwidthAvailable = bandwidthTotal; }
	
	private List< VirtualLink > virtualLinks = new ArrayList< VirtualLink >();
	public List< VirtualLink > getVirtualLinks(){ return this.virtualLinks; }
	public void addVirtualLink( VirtualLink virtualLink ){ virtualLinks.add( virtualLink ); }
	public void resetVirtualLinks(){ virtualLinks = new ArrayList< VirtualLink >(); }
	
	public void release( VirtualLink virtualLink )
	{
		this.bandwidthAvailable += virtualLink.getBandwidth();
		this.virtualLinks.remove( virtualLink );
	}
}
